package com.n9.qqonline.sales.service;

import com.n9.component.table.AnnotationTableModel;
import com.n9.db.util.GenericService;
import com.n9.qq.util.ThreadUtils;
import com.n9.qqonline.sales.entity.*;
import com.n9.qqonline.sales.product.ExcelFileLoader;
import com.n9.qqonline.sales.product.MemoryPatentService;
import com.n9.qqonline.sales.product.Patent;
import com.n9.qqonline.sales.product.ServerLoader;
import com.n9.qqonline.sales.view.AddAccountForm;
import com.n9.qqonline.sales.view.DialogUtils;
import com.n9.qqonline.sales.view.MainForm;
import com.n9.qqonline.sales.vo.BuyMsgVo;
import com.n9.qqonline.sales.vo.QqVo;
import com.n9.util.DateUtils;
import com.n9.util.StringUtils;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.event.ActionEvent;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author ice
 * @since 2019/3/7 16:30
 */
public final class FormService {
    /**
     * 日志控件最大容量
     */
    private static final int MAX_LOG_SIZE = 5 * 1024;
    private MainForm mainForm;
    private AddAccountForm addAccountForm;

    Thread thread = new Thread() {
        private long TIME_GAP = 1 * 60 * 1000;//每隔1分钟获取专利

        @Override
        public void run() {
            while(true) {
                try {
                    setPatentsFromServer(false);
                } catch (Exception e) {
                    log("获取最新专利清单失败......5分钟后重新获取");
                }
                ThreadUtils.sleep(TIME_GAP);
            }
        }
    };

    public FormService() {
        this.mainForm = MainForm.instance();
        this.addAccountForm = AddAccountForm.instance();
    }

    /**
     * 显示日志
     * @param log
     */
    public void log(String log) {
        if (Objects.isNull(log) || log.isEmpty()) {
            return;
        }

        SwingUtilities.invokeLater(()->{
            JTextArea logTextArea = mainForm.getLogTextArea();
            if (logTextArea.getText().length() > MAX_LOG_SIZE) {
                logTextArea.setText("");
            }
            logTextArea.append(DateUtils.currentDatetimeStr());
            logTextArea.append(": ");
            logTextArea.append(log);
            logTextArea.append("\r\n");
        });
    }

    /**
     * 打开主窗口
     */
    public void openMainForm() {
        mainForm.setVisible(true);
    }

    /**
     * 初始化显示
     */
    public void initView() {
        viewQQAccounts();

        Config config = new ConfigService().getConfig();
        if (Objects.nonNull(config)) {
            mainForm.setKeyWords(config.getBuyKeyWords(), config.getSearchKeyWords());
            mainForm.setPatentFilePath(config.getPatentFilePath());

            thread.setDaemon(true);
            thread.start();
            //setPatentsFromServer(false);
        }

        viewNextBuyMsg();

        BuyMsgReport.instance().setReportView(buyMsgReport-> mainForm.setUnReadMsgCount(buyMsgReport.getTotalCount(), buyMsgReport.getUnReadCount()));
        viewBuyMsgCount();
        viewReadMsg();
    }

    private void viewReadMsg() {
        GenericService genericService = new GenericService();
        List<BuyMsg> msgs = genericService.queryAll(String.format("FROM BuyMsg WHERE readStatus = '%s' ORDER BY readTime ", ReadStatus.READ));
        List<BuyMsgVo> vos = new ArrayList<>();

        int count = 0;
        for (int i = 0; i < msgs.size(); i++) {
            if (count >= 30) {
                break;
            }

            BuyMsg msg = msgs.get(i);
            RecvMsg recvMsg = genericService.getByHql(String.format("FROM RecvMsg WHERE sign = '%s'", msg.getSign()));
            if (Objects.nonNull(recvMsg)) {
                count++;
                vos.add(buyMsg2Vo(msg, recvMsg));
            }
        }
        mainForm.setReadedMsg(vos);
    }

    /**
     * 显示未读消息数量
     */
    private void viewBuyMsgCount() {
        GenericService genericService = new GenericService();
        long unReadCount = genericService.count(String.format("SELECT COUNT (*) FROM BuyMsg WHERE readStatus = '%s'", ReadStatus.UN_READ));
        long totalCount = genericService.count("SELECT COUNT (*) FROM BuyMsg");
        BuyMsgReport.instance().setUnreadCount(totalCount, unReadCount);
    }

    /**
     * 在表格中显示账号
     */
    private void viewQQAccounts() {
        List<QqAccount> qqAccounts = new GenericService().queryAll("From QqAccount");
        List<QqVo> vos = new ArrayList<>();
        qqAccounts.forEach((account) -> vos.add(new QqVo(account.getQqUin(), account.getPassword())));
        mainForm.getQqTableModel().setRows(vos);
    }

    /**
     * 按钮事件
     * @param e
     */
    public void doActionPerformed(ActionEvent e) {
        switch (e.getActionCommand()) {
            case "设置账号":
                addAccountForm.setVisible(true);
                break;
            case "启动":
                startBtn();
                break;
            case "求购关键词":
                saveBuyKeyWords();
                break;
            case "设置本地专利":
                setPatentsFromLocal();
                break;
            case "设置远程专利":
                setPatentsFromServer(true);
                break;
            case "有效":
                readCurrentMsgAndViewNext(MatchPrecision.LV1);
                break;
            case "无效":
                readCurrentMsgAndViewNext(MatchPrecision.LV0);
                break;
            case "复位有效消息":
                resetBuyMsg();
                break;
            case "搜索":
                searchBuyMsg();
                break;
            case "清空消息":
                deleteBuyMsgAndRecvMsg();
                break;
            case "ADD_ACCOUNT_OK":
                importQqVos();
                break;
            case "ADD_ACCOUNT_CANCEL":
                hiddenAddAccountForm();
                break;
            case "导出":
                exportMsg();
                break;
            default:
                break;
        }
    }

    /**
     * 复位求购消息
     */
    private void resetBuyMsg() {
        String dayStr = MainForm.instance().getRestDay();

        LocalDate day = null;
        try {
            day = LocalDate.parse(dayStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (day == null) {
            JOptionPane.showMessageDialog(mainForm, "日期格式应为:2020-01-20", "求购消息复位失败", JOptionPane.ERROR_MESSAGE);
        }

        GenericService genericService = new GenericService();
        genericService.execHql(String.format("UPDATE BuyMsg SET readStatus = '%s' WHERE day='%s' AND matchPrecision = '%s'", ReadStatus.UN_READ, dayStr, MatchPrecision.LV1));

        JOptionPane.showMessageDialog(mainForm, "求购消息复位成功", "dayStr的有效求购消息复位成功", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * 导出消息
     */
    private void exportMsg() {
        //TODO
//        ExcelUtils.writeToExcel();
    }

    /**
     * 搜索求购信息
     */
    private void searchBuyMsg() {
        String searchKeyWordsString = mainForm.getSearchKeyWordStr();
        ConfigService configService = new ConfigService();
        Config config = configService.getConfig();
        config.setSearchKeyWords(searchKeyWordsString);
        configService.saveOrUpdate(config);
        viewNextBuyMsg();
    }

    private void setPatentsFromServer(boolean isDialogNotice) {
        new ServerLoader().load((msg)-> {
            log(msg);
            if (isDialogNotice) {
                JOptionPane.showMessageDialog(mainForm, msg, "设置成功", JOptionPane.INFORMATION_MESSAGE);
            }
        });
    }

    /**
     * 设置本地专利
     */
    private void setPatentsFromLocal() {
        JFileChooser chooser = new JFileChooser();
        chooser.setDialogType(JFileChooser.OPEN_DIALOG);
        chooser.setMultiSelectionEnabled(false);
        chooser.setFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                if (Objects.isNull(f) || !f.isFile()) {
                    return false;
                }
                String fileName = f.getName();
                return  fileName.endsWith(".xls") || fileName.endsWith(".xlsx");
            }
            @Override
            public String getDescription() {
                return "excel文件";
            }
        });
        int ret = chooser.showOpenDialog(mainForm);
        if (ret == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            new MemoryPatentService().clear();
            String patentFilePath = file.getAbsolutePath();
            mainForm.setPatentFilePath(patentFilePath);

            ExcelFileLoader excelFileLoader = new ExcelFileLoader(mainForm.getPatentFilePath());
            excelFileLoader.load((msg) -> log(msg));

            ConfigService configService =  new ConfigService();
            Config config = configService.getConfig();
            config.setPatentFilePath(patentFilePath);
            configService.saveOrUpdate(config);

            JOptionPane.showMessageDialog(mainForm, "专利清单设置成功", "设置成功", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    private void deleteBuyMsgAndRecvMsg() {
        int result = JOptionPane.showConfirmDialog(mainForm, "是否清空求购信息?", "确认", JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);

        if (result == JOptionPane.OK_OPTION) {
            new GenericService().execUpdate((session)->{
                session.createQuery("DELETE FROM BuyMsg").executeUpdate();
                session.createQuery("DELETE FROM RecvMsg").executeUpdate();
            });

            viewBuyMsgCount();
            viewNextBuyMsg();
            log("求购信息清空成功");
        }
    }

    /**
     * 保存求购关键词
     */
    private void saveBuyKeyWords() {
        String buyKeyWords = mainForm.getBuyKeyWords();
        ConfigService configService = new ConfigService();

        Config config = configService.getConfig();
        config.setBuyKeyWords(buyKeyWords);
        configService.saveOrUpdate(config);

        JOptionPane.showMessageDialog(mainForm, "求购关键词更新成功", "操作成功", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * 软件启动
     */
    private void startBtn() {
        AnnotationTableModel<QqVo> qqTableModel = mainForm.getQqTableModel();
        List<QqVo> rows = qqTableModel.getRows();
        if (rows.isEmpty()) {
            log("请先添加账号");
            return;
        }

        Config config = new ConfigService().getConfig();
        if (Objects.isNull(config) || !StringUtils.hasText(config.getBuyKeyWords())) {
            log("请先添加求购信息的关键词");
            return;
        }

        List<String> tags = new MemoryPatentService().getTags();
        if (tags.isEmpty()) {
            int ret = JOptionPane.showConfirmDialog(mainForm, "尚未配置专利清单,是否继续启动?", "启动确认", JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
            if (ret == JOptionPane.CANCEL_OPTION) {
                return;
            }
        }

        mainForm.getAddAccountBtn().setEnabled(false);
        mainForm.getStartBtn().setEnabled(false);
        new Thread(()->
            rows.forEach(qqVo -> {
                boolean result = MsgService.instance().login(qqVo.getUin(), qqVo.getPassword());
                if(!result) {
                    JOptionPane.showMessageDialog(mainForm, qqVo.getUin() + "登陆失败，请重开软件", "登陆失败", JOptionPane.ERROR_MESSAGE);
                }
            })
        ).start();
    }

    public void updateQQInfo(QqVo qqVo) {
        mainForm.getQqTableModel().updateRow(qqVo);
    }

    /**
     * 导入账号
     */
    private void importQqVos() {
        String accountsString = addAccountForm.getAccountsString().trim();
        if (!StringUtils.hasText(accountsString)) {
            clearQqAccount();
            viewQQAccounts();
            hiddenAddAccountForm();
            log("清空账号");
            return;
        }


        List<QqAccount> qqAccounts = new ArrayList<>();
        String[] accounts = accountsString.split("\n");
        for (int i = 0; i < accounts.length; i++) {
            String line = accounts[i];
            String[] split = line.split("----");
            if (split.length != 2) {
                log("账号格式有误:" + line);
                return;
            } else {
                try {
                    Long qqUin = Long.valueOf(split[0]);
                    String password = split[1];
                    QqAccount account = new QqAccount();
                    account.setQqUin(qqUin);
                    account.setPassword(password);
                    qqAccounts.add(account);
                } catch (Exception e) {
                    log("账号错误:" + line);
                    return;
                }
            }
        }

        clearQqAccount();
        new GenericService().saveBatch(qqAccounts);

        viewQQAccounts();
        hiddenAddAccountForm();
        log(String.format("账号设置成功,当前账号数:%d个", qqAccounts.size()));
    }

    private void clearQqAccount() {
        new GenericService().execHql("DELETE FROM QqAccount");
    }

    /**
     * 隐藏添加账号窗口
     */
    private void hiddenAddAccountForm() {
        addAccountForm.clearAccounts();
        addAccountForm.setVisible(false);
    }


    /**
     * 当前消息设置为已读，且显示下一条求购信息
     */
    private void readCurrentMsgAndViewNext(MatchPrecision matchPrecision) {
        BuyMsgVo msg = mainForm.getCurrentMsg();
        if (Objects.isNull(msg)) {
            log("当前求购信息为空,无法处理");
        } else {
            GenericService genericService = new GenericService();
            BuyMsg buyMsg = genericService.get(BuyMsg.class, msg.getId());
            if (Objects.nonNull(buyMsg)) {
                buyMsg.setReadStatus(ReadStatus.READ);
                buyMsg.setReadTime(new Date());
                buyMsg.setMatchPrecision(matchPrecision);
                buyMsg.setNotes(mainForm.getMsgNotes());

                genericService.update(buyMsg);
                log(String.format("QQ:%d群:%s,发送人:(%d)的求购消息处理完毕", msg.getRecvQQUin(), msg.getRecvGroupName(), msg.getSendQQUin()));

                msg.setReadTime(DateUtils.formatTime(buyMsg.getReadTime()));
                msg.setNotes(buyMsg.getNotes());
            }
            mainForm.addReadedMsg(msg);
        }
        viewNextBuyMsg();
        viewBuyMsgCount();

    }

    /**
     * 显示求购信息
     */
    public void viewNextBuyMsg() {
        BuyMsgVo buyMsgVo = nextUnReadBuyMsg();
        mainForm.viewBuyMsg(buyMsgVo);
    }

    /**
     * 获取下一条未读消息
     * @return
     */
    private BuyMsgVo nextUnReadBuyMsg() {
        BuyMsgVo buyMsgVo = null;
        String[] searchKeyWords = getSearchKeyWords();
        if (Objects.nonNull(searchKeyWords) && searchKeyWords.length > 0) {
            buyMsgVo = nextUnReadBuyMsg(searchKeyWords);
        }

        if (Objects.isNull(buyMsgVo)) {
            buyMsgVo = nextUnReadBuyMsg(new String[0]);
        }
        return buyMsgVo;
    }

    /**
     * 获取下一条未读消息
     * @return
     */
    private BuyMsgVo nextUnReadBuyMsg(String[] searchKeyWords) {
        StringBuilder hql = new StringBuilder();
        for (int i = 0; i < searchKeyWords.length; i++) {
            if (hql.length() > 0) {
                hql.append(" OR ");
            }
            hql.append(" content LIKE '%");
            hql.append(searchKeyWords[i]);
            hql.append("%' ");
        }

        if (hql.length() > 0) {
            hql.insert(0, String.format("FROM BuyMsg WHERE readStatus = '%s' AND ( ", ReadStatus.UN_READ));
            hql.append(" ) ");
        } else {
            hql.append(String.format("FROM BuyMsg WHERE readStatus = '%s'", ReadStatus.UN_READ));
        }
        hql.append(" ORDER BY createTime DESC");

        GenericService genericService = new GenericService();
        BuyMsg buyMsg = genericService.getByHql(hql.toString());
        if (Objects.isNull(buyMsg)) {
            return null;
        }

        RecvMsg recvMsg = genericService.getByHql(String.format("FROM RecvMsg WHERE sign = '%s'", buyMsg.getSign()));
        if (Objects.isNull(recvMsg)) {
            return null;
        }

        return buyMsg2Vo(buyMsg, recvMsg);
    }

    private BuyMsgVo buyMsg2Vo(BuyMsg buyMsg, RecvMsg recvMsg) {
        BuyMsgVo vo = new BuyMsgVo();
        vo.setId(buyMsg.getId());
        vo.setDay(buyMsg.getDay());
        vo.setReadStatus(buyMsg.getReadStatus());
        vo.setSign(buyMsg.getSign());
        vo.setContent(buyMsg.getContent());
        vo.setSendQQUin(recvMsg.getSendQQUin());
        vo.setSendNick(recvMsg.getSendNick());
        vo.setRecvQQUin(recvMsg.getRecvQQUin());
        vo.setRecvGroupCode(recvMsg.getRecvGroupCode());
        vo.setRecvGroupName(recvMsg.getRecvGroupName());
        vo.setRecvTime(recvMsg.getRecvTime());
        Date readTime = buyMsg.getReadTime();
        if (Objects.nonNull(readTime)) {
            vo.setReadTime(DateUtils.formatTime(readTime));
        }
        vo.setNotes(buyMsg.getNotes());
        return vo;
    }


    /**
     * 获取搜索关键词
     * @return
     */
    private String[] getSearchKeyWords() {
        String searchKeyWordStr = mainForm.getSearchKeyWordStr();
        return searchKeyWordStr.split(Config.SEPARATOR_REGEX);
    }
}
